package com.jing.yao.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.read.listener.ReadListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
public class ReadExcelListener<T> implements ReadListener<T> {

    /**
     * 记录日志
     */
    protected Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * excel最大行数
     */
    private static final int MAX_COUNT = 5000;
    /**
     * 这里context.readRowHolder().getRowIndex()获取到的行号是正文的行号，要在前台使用要加上表头的行数
     */
    private static final int HEADER_ROWS = 1;
    private final List<T> dataList;
    private ExcelResult<T> result;
    private List<ExcelErrorInfo> errorInfo;
    private Validate<T> validate;
    private Boolean success = true;
    private Integer operationType;
    /**
     * 序号
     * */
    private int NUMBER_INDEX=1;

    public ReadExcelListener(ExcelResult<T> result, Validate<T> validate, Integer operationType) {
        this.result = result;
        this.validate = validate;
        this.dataList = result.getDataList();
        this.errorInfo = result.getErrorInfos();
        this.operationType = operationType;
    }

    /**
     * All listeners receive this method when any one Listener does an error report. If an exception is thrown here, the
     * entire read will terminate.
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        log.warn("导入异常", exception);
        int row = context.readRowHolder().getRowIndex() + HEADER_ROWS;
        log.warn("第{}行解析出错", row);
        success = false;
        dataList.clear();
        if (exception instanceof ClassCastException || exception instanceof ExcelDataConvertException) {
            errorInfo.add(new ExcelErrorInfo(row, "数据与模板不匹配",0));
        }
    }

    /**
     * When analysis one head row trigger invoke function.
     *
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        String errorMessage = validate.validate(data, operationType, context.readRowHolder().getRowIndex());

        if (errorMessage != null && success) {
            success = false;
            dataList.clear();
            errorInfo.add(new ExcelErrorInfo(context.readRowHolder().getRowIndex() + HEADER_ROWS, errorMessage,NUMBER_INDEX++));
        } else if (errorMessage != null) {
            errorInfo.add(new ExcelErrorInfo(context.readRowHolder().getRowIndex() + HEADER_ROWS, errorMessage,NUMBER_INDEX++));
        } else if (success) {
            if (dataList.size() < MAX_COUNT) {
                dataList.add(data);
            } else {
                throw new RuntimeException("data is too long");
            }
        }
    }

    @Override
    public void extra(CellExtra cellExtra, AnalysisContext analysisContext) {

    }

    /**
     * if have something to do after all analysis
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if(context.readRowHolder().getRowIndex() > MAX_COUNT){
            errorInfo.clear();
            errorInfo.add(new ExcelErrorInfo(0,"导入数据不能超过"+MAX_COUNT,0));
        }

        result.setSuccess(success);
    }
    /**
     * Verify that there is another piece of data.You can stop the read by returning false
     *
     * @param context
     * @return
     */
    @Override
    public boolean hasNext(AnalysisContext context) {
        return true;
    }

}
